using System.Collections;
using System.Collections.Generic;
using DataUtility = UnityEngine.Sprites.DataUtility;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace UnityEngine.UI
{
    /// <summary>
    /// TP形Image. 
    /// </summary>
    // [AddComponentMenu("SoarDUI/SDImage", 01)]
    public class SDImageBase : Image
    {
        [SerializeField]
        private string m_SpriteName;
        [SerializeField]
        private bool m_UseSpritePacker;
        #region 异形裁剪
        public enum ShapeType
        {
            None,
            Square,
            Circle,
            Rectangle,
        }
        public enum ShapeAnchors
        {
            Center,
            Top,
            Bottom,
            Left,
            Right,
            TopLeft,
            TopRight,
            BottomLeft,
            BottomRight,
        }
        //裁剪模式（目前仅用在矩形裁剪中）
        public enum CutMode
        {
            Vertical = 1,    //竖直方向裁剪
            Horizontal = 2,  //水平方向裁剪
        }
        [SerializeField]
        private ShapeType m_ShapeType = ShapeType.None;
        public ShapeType shapeType { get { return m_ShapeType; } set { if (SetPropertyUtility.SetStruct(ref m_ShapeType, value)) SetVerticesDirty(); } }
        [SerializeField]
        private ShapeAnchors m_ShapeAnchors = ShapeAnchors.Center; // 裁剪锚点
        public ShapeAnchors shapeAnchorsType { get { return m_ShapeAnchors; } set { if (SetPropertyUtility.SetStruct(ref m_ShapeAnchors, value)) SetVerticesDirty(); } }
        [VectorRange(-1f, 1f, -1f, 1f, true), SerializeField]
        private Vector2 m_ShapeAnchorsOffSet = Vector2.zero; // 锚点偏移
        public Vector2 shapeAnchorsOffSet { get { return m_ShapeAnchorsOffSet; } set { if (SetPropertyUtility.SetStruct(ref m_ShapeAnchorsOffSet, value)) SetVerticesDirty(); } }
        [SerializeField]
        private bool m_ShapeAnchorsCalPadding = false; // 裁剪锚点是否计算padding
        [Range(0f, 1f), SerializeField]
        private float m_ShapeScale = 1f; // 裁剪缩放
        public float shapeScale { get { return m_ShapeScale; } set { if (SetPropertyUtility.SetStruct(ref m_ShapeScale, value)) SetVerticesDirty(); } }
        [Range(1f, 50f), SerializeField]
        int m_CircleShape_Segements = 25; // 圆形等分面数
        public int circleShape_Segements { get { return m_CircleShape_Segements; } set { if (SetPropertyUtility.SetStruct(ref m_CircleShape_Segements, value)) SetVerticesDirty(); } }
        [Range(0f, 1f), SerializeField]
        float m_CircleShape_FillPercent = 1f; // 显示比例
        public float circleShape_FillPercent { get { return m_CircleShape_FillPercent; } set { if (SetPropertyUtility.SetStruct(ref m_CircleShape_FillPercent, value)) SetVerticesDirty(); } }
        [SerializeField]
        private CutMode m_RectangleShape_CutMode = CutMode.Vertical;
        public CutMode cutMode { get { return m_RectangleShape_CutMode; } set { if (SetPropertyUtility.SetStruct(ref m_RectangleShape_CutMode, value)) SetVerticesDirty(); } }
        #endregion
        public bool m_IsUrl = false;

        public bool IsUrl()
        {
            return m_IsUrl;
        }

        private AtlasReference m_AtlasRef;
        public AtlasReference GetAtlasReference()
        {
            if (m_AtlasRef == null)
            {
                m_AtlasRef = gameObject.GetComponentInParent<AtlasReference>();
            }
            return m_AtlasRef;
        }

        public string SpriteName
        {
            get
            {
                return m_SpriteName;
            }
            set
            {
                m_SpriteName = value;
            }
        }

        public bool UseSpritePacker
        {
            get
            {
                return m_UseSpritePacker;
            }
            set
            {
                m_UseSpritePacker = value;
            }
        }

        private static Dictionary<string, Vector4> m_spritePaddings;
        private static Dictionary<string, bool> m_spriteIsPoly;

        protected SDImageBase()
        {
            useLegacyMeshGeneration = false;
        }

        public static void SetPaddingConfig(Dictionary<string, Vector4> paddings)
        {
            m_spritePaddings = paddings;
        }
        public static void SetIsPolyConfig(Dictionary<string, bool> isPoly)
        {
            m_spriteIsPoly = isPoly;
        }

        public override Material material
        {
            get
            {
                return m_Material;
            }

            set
            {
                if (m_Material && value && m_Material.name == value.name) return;
                m_Material = value;
            }
        }

        public Mask m_Mask;    // 缓存mask组件，如果后面有动态添加，记得set一下
        public Mask CachedMask
        {
            get
            {
                return m_Mask;
            }
            set
            {
                m_Mask = value;
            }
        }

#if UNITY_EDITOR
        [SLua.DoNotToLua]
        public bool IsEmptyImage
        {
            get { return (sprite == null && string.IsNullOrEmpty(SpriteName) && m_Material == null); }
        }

        [SLua.DoNotToLua]
        public bool IsMissing
        {
            get
            {
                return (sprite == null || string.IsNullOrEmpty(SpriteName) || m_Material == null ||
                        SpriteName != sprite.name);
            }
        }
#endif
        protected bool GetIsPoly()
        {
            if (Application.isPlaying)
            {
                if (m_IsUrl || string.IsNullOrEmpty(SpriteName))
                {
                    return false;
                }
                if (m_spriteIsPoly == null)
                {
                    //Debug.LogError("SpriteIsPoly error");
                    return false;
                }
                if (m_spriteIsPoly.ContainsKey(SpriteName))
                {
                    return m_spriteIsPoly[SpriteName];
                }
                return false;
            }
#if UNITY_EDITOR
            if (!overrideSprite)
                return false;
            if (UseSpritePacker)
            {
                return false;
            }
            if (true)
            {
                string path = Config.UI_ATLAS_PATH;
                PaddingData paddingData = AssetDatabase.LoadAssetAtPath<PaddingData>(path);
                m_spriteIsPoly = new Dictionary<string, bool>();
                foreach (var atlas in paddingData.atlas)
                {
                    foreach (var spriteInfo in atlas.sprites)
                    {
                        if (m_spriteIsPoly.ContainsKey(spriteInfo.name)) continue;
                        m_spriteIsPoly.Add(spriteInfo.name, atlas.isPoly);
                    }
                }
            }
            if (!m_spriteIsPoly.ContainsKey(overrideSprite.name))
            {
                //Debuger.LogError("图集错误. 白边信息缺失: sprite:" + overrideSprite.name);
                return false;
            }
            return m_spriteIsPoly[overrideSprite.name];
#else
            return false;
#endif
        }
        protected Vector4 GetPadding()
        {
            if (Application.isPlaying)
            {
                if (m_IsUrl || string.IsNullOrEmpty(SpriteName))
                {
                    return Vector4.zero;
                }
                if (m_spritePaddings == null)
                {
                    //Debug.LogError("SpritePadding error");
                    return Vector4.zero;
                }
                if (m_spritePaddings.ContainsKey(SpriteName))
                {
                    return m_spritePaddings[SpriteName];
                }
                return Vector4.zero;
            }
#if UNITY_EDITOR
            if (!overrideSprite)
                return Vector4.zero;
            if (UseSpritePacker)
            {
                return DataUtility.GetPadding(overrideSprite);
            }
            if (true)
            {
                string path = Config.UI_ATLAS_PATH;
                PaddingData paddingData = AssetDatabase.LoadAssetAtPath<PaddingData>(path);
                m_spritePaddings = new Dictionary<string, Vector4>();
                foreach (var atlas in paddingData.atlas)
                {
                    foreach (var spriteInfo in atlas.sprites)
                    {
                        if (m_spritePaddings.ContainsKey(spriteInfo.name)) continue;
                        m_spritePaddings.Add(spriteInfo.name, spriteInfo.padding);
                    }
                }
            }
            if (!m_spritePaddings.ContainsKey(overrideSprite.name))
            {
                //Debuger.LogError("图集错误. 白边信息缺失: sprite:" + overrideSprite.name);
                return Vector4.zero;
            }
            return m_spritePaddings[overrideSprite.name];
#else
            return Vector4.zero;
#endif
        }

        //X = left, Y = bottom, Z = right, W = top.
        protected Vector4 GetDrawingDimensions(bool shouldPreserveAspect)
        {
            Sprite overrideSprite = this.overrideSprite;
            var padding = GetPadding();
            var size = overrideSprite == null ? Vector2.zero : new Vector2(overrideSprite.rect.width, overrideSprite.rect.height);
            Rect r = GetPixelAdjustedRect();
            int spriteW = Mathf.RoundToInt(size.x);
            int spriteH = Mathf.RoundToInt(size.y);
            float width = spriteW + padding.z + padding.x;
            float height = spriteH + padding.w + padding.y;

            var v = new Vector4(
                    padding.x / width,
                    padding.y / height,
                    (width - padding.z) / width,
                    (height - padding.w) / height);

            if (shouldPreserveAspect && size.sqrMagnitude > 0.0f)
            {
                var spriteRatio = size.x / size.y;
                var rectRatio = r.width / r.height;

                if (spriteRatio > rectRatio)
                {
                    var oldHeight = r.height;
                    r.height = r.width * (1.0f / spriteRatio);
                    r.y += (oldHeight - r.height) * rectTransform.pivot.y;
                }
                else
                {
                    var oldWidth = r.width;
                    r.width = r.height * spriteRatio;
                    r.x += (oldWidth - r.width) * rectTransform.pivot.x;
                }
            }

            v = new Vector4(
                    r.x + r.width * v.x,
                    r.y + r.height * v.y,
                    r.x + r.width * v.z,
                    r.y + r.height * v.w
                    );

            return v;
        }

        /// <summary>
        /// sliced特有Diamons, 在Sliced拉伸模式 Padding不拉伸
        /// </summary>
        /// <returns></returns>
        private Vector4 GetSlicedDiamons()
        {
            var padding = GetPadding();
            Rect r = GetPixelAdjustedRect();
            //原尺寸定死
            return new Vector4(
                    r.x + padding.x,
                    r.y + padding.y,
                    r.x + r.width - padding.z,
                    r.y + r.height - padding.w
                    );
        }

        /// <summary>
        /// 更新UI渲染网格(Polygon模式未开启)
        /// </summary>
        protected override void OnPopulateMesh(VertexHelper toFill)
        {
            _hasInitPopulateMesh = true;
            if (overrideSprite == null)
            {
                base.OnPopulateMesh(toFill);
                return;
            }
            switch (type)
            {
                case Type.Simple:
                    if (m_ShapeType == ShapeType.Circle)
                    {
                        GenerateSimpleCircleSprite(toFill, preserveAspect);
                    }
                    else if (m_ShapeType == ShapeType.Square)
                    {
                        GenerateSimpleSquareSprite(toFill, preserveAspect);
                    }
                    else if (m_ShapeType == ShapeType.Rectangle)
                    {
                        GenerateSimpleRectangleSprite(toFill, preserveAspect);
                    }
                    else
                    {
                        GenerateSimpleSprite(toFill, preserveAspect);
                    }
                    break;
                case Type.Sliced:
                    GenerateSlicedSprite(toFill);
                    break;
                case Type.Tiled:
                    GenerateTiledSprite(toFill);
                    break;
                case Type.Filled:
                    GenerateFilledSprite(toFill, preserveAspect);
                    break;
            }
        }
        #region shape自定义
        /// <summary>
        /// shape锚点设置.
        /// </summary>
        Vector4 SetShapeAnchors(Vector4 uv)
        {
            Sprite overrideSprite = this.overrideSprite;
            if (overrideSprite == null)
            {
                return uv;
            }
            float tw = overrideSprite.texture.width;
            float th = overrideSprite.texture.height;
            float s = tw / th;
            float dx = (uv.z - uv.x) * s;
            float dy = (uv.w - uv.y);
            float d = dx - dy;//d>0 宽大于高，d<0 高大于宽
            if (d < 0)
            {
                if (shapeAnchorsType == ShapeAnchors.Top || shapeAnchorsType == ShapeAnchors.TopLeft || shapeAnchorsType == ShapeAnchors.TopRight)
                {
                    uv.y -= d;
                }
                else if (shapeAnchorsType == ShapeAnchors.Center || shapeAnchorsType == ShapeAnchors.Left || shapeAnchorsType == ShapeAnchors.Right)
                {
                    uv.y -= d / 2;
                    uv.w += d / 2;
                }
                else if (shapeAnchorsType == ShapeAnchors.Bottom || shapeAnchorsType == ShapeAnchors.BottomLeft || shapeAnchorsType == ShapeAnchors.BottomRight)
                {
                    uv.w += d;
                }
            }
            else
            {
                if (shapeAnchorsType == ShapeAnchors.Center || shapeAnchorsType == ShapeAnchors.Top || shapeAnchorsType == ShapeAnchors.Bottom)
                {
                    uv.x += d / 2;
                    uv.z -= d / 2;
                }
                else if (shapeAnchorsType == ShapeAnchors.Left || shapeAnchorsType == ShapeAnchors.TopLeft || shapeAnchorsType == ShapeAnchors.BottomLeft)
                {
                    uv.z -= d;
                }
                else if (shapeAnchorsType == ShapeAnchors.Right || shapeAnchorsType == ShapeAnchors.TopRight || shapeAnchorsType == ShapeAnchors.BottomRight)
                {
                    uv.x += d;
                }
            }
            return uv;
        }
        Vector4 SetShapeAnchorsOffset(Vector4 uv)
        {
            var dw = uv.z - uv.x;
            var dh = uv.w - uv.y;
            uv.x += dw * m_ShapeAnchorsOffSet.x;
            uv.z += dw * m_ShapeAnchorsOffSet.x;
            uv.y += dh * m_ShapeAnchorsOffSet.y;
            uv.w += dh * m_ShapeAnchorsOffSet.y;
            return uv;
        }
        Vector4 SetShapeScale(Vector4 uv)
        {
            if (overrideSprite == null)
            {
                return uv;
            }
            float scale = 1 - m_ShapeScale;
            float dx = (uv.z - uv.x) * scale;
            float dy = (uv.w - uv.y) * scale;
            if (shapeAnchorsType == ShapeAnchors.Center || shapeAnchorsType == ShapeAnchors.Top || shapeAnchorsType == ShapeAnchors.Bottom)
            {
                uv.x += dx * 0.5f;
                uv.z -= dx * 0.5f;
            }
            if (shapeAnchorsType == ShapeAnchors.Center || shapeAnchorsType == ShapeAnchors.Left || shapeAnchorsType == ShapeAnchors.Right)
            {
                uv.y += dy * 0.5f;
                uv.w -= dy * 0.5f;
            }
            if (shapeAnchorsType == ShapeAnchors.Bottom || shapeAnchorsType == ShapeAnchors.BottomLeft || shapeAnchorsType == ShapeAnchors.BottomRight)
            {
                uv.w -= dy;
            }
            if (shapeAnchorsType == ShapeAnchors.Top || shapeAnchorsType == ShapeAnchors.TopLeft || shapeAnchorsType == ShapeAnchors.TopRight)
            {
                uv.y += dy;
            }
            if (shapeAnchorsType == ShapeAnchors.Left || shapeAnchorsType == ShapeAnchors.TopLeft || shapeAnchorsType == ShapeAnchors.BottomLeft)
            {
                uv.z -= dx;
            }
            if (shapeAnchorsType == ShapeAnchors.Right || shapeAnchorsType == ShapeAnchors.TopRight || shapeAnchorsType == ShapeAnchors.BottomRight)
            {
                uv.x += dx;
            }
            return uv;
        }
        Vector4 IncludePaddingUV(Vector4 uv)
        {
            Sprite overrideSprite = this.overrideSprite;
            if (overrideSprite == null)
            {
                return uv;
            }
            var old_uv = Sprites.DataUtility.GetOuterUV(overrideSprite);
            var padding = GetPadding();
            float width = overrideSprite.rect.width;
            float height = overrideSprite.rect.height;
            float odx = old_uv.z - old_uv.x;
            float ody = old_uv.w - old_uv.y;
            float px = padding.x / width * odx;
            float pz = padding.z / width * odx;
            float pw = padding.w / height * ody;
            float py = padding.y / height * ody;
            if (shapeAnchorsType == ShapeAnchors.Center || shapeAnchorsType == ShapeAnchors.Top || shapeAnchorsType == ShapeAnchors.Bottom)
            {
                uv.x += (pz - px) / 2;
                uv.z += (pz - px) / 2;
            }
            if (shapeAnchorsType == ShapeAnchors.Center || shapeAnchorsType == ShapeAnchors.Left || shapeAnchorsType == ShapeAnchors.Right)
            {
                uv.y += (py - pw) / 2;
                uv.w += (py - pw) / 2;
            }
            if (shapeAnchorsType == ShapeAnchors.Bottom || shapeAnchorsType == ShapeAnchors.BottomLeft || shapeAnchorsType == ShapeAnchors.BottomRight)
            {
                uv.y -= pw;
                uv.w -= pw;
            }
            if (shapeAnchorsType == ShapeAnchors.Top || shapeAnchorsType == ShapeAnchors.TopLeft || shapeAnchorsType == ShapeAnchors.TopRight)
            {
                uv.y += py;
                uv.w += py;
            }
            if (shapeAnchorsType == ShapeAnchors.Left || shapeAnchorsType == ShapeAnchors.TopLeft || shapeAnchorsType == ShapeAnchors.BottomLeft)
            {
                uv.z -= px;
                uv.x -= px;
            }
            if (shapeAnchorsType == ShapeAnchors.Right || shapeAnchorsType == ShapeAnchors.TopRight || shapeAnchorsType == ShapeAnchors.BottomRight)
            {
                uv.z += pz;
                uv.x += pz;
            }
            return uv;
        }
        //设置矩形图的UV
        Vector4 SetRectangleShapeUV(Vector4 uv)
        {
            Sprite overrideSprite = this.overrideSprite;
            if (overrideSprite == null)
            {
                return uv;
            }

            float rectWidth = this.rectTransform.rect.width;
            float rectHeight = this.rectTransform.rect.height;

            float textureWitdh = overrideSprite.rect.width;
            float textureHeight = overrideSprite.rect.height;

            if (m_RectangleShape_CutMode == CutMode.Horizontal)  //水平方向裁剪，竖直方向保持完整
            {
                float uvWidth = uv.z - uv.x;
                float preferredRectWidth = (rectHeight / textureHeight) * textureWitdh;
                float widthScale = rectWidth / preferredRectWidth;
                float uvDeltaX = (1 - Mathf.Clamp01(widthScale)) * uvWidth;

                if (shapeAnchorsType == ShapeAnchors.Left || shapeAnchorsType == ShapeAnchors.TopLeft || shapeAnchorsType == ShapeAnchors.BottomLeft)
                {
                    uv.z -= uvDeltaX;
                }
                else if (shapeAnchorsType == ShapeAnchors.Center || shapeAnchorsType == ShapeAnchors.Top || shapeAnchorsType == ShapeAnchors.Bottom)
                {
                    uv.z -= uvDeltaX / 2;
                    uv.x += uvDeltaX / 2;
                }
                else if (shapeAnchorsType == ShapeAnchors.Right || shapeAnchorsType == ShapeAnchors.TopRight || shapeAnchorsType == ShapeAnchors.BottomRight)
                {
                    uv.x += uvDeltaX;
                }
            }
            else   //竖直方向裁剪，水平方向保持完整
            {
                float uvHeight = uv.w - uv.y;
                float preferredRectHeight = (rectWidth / textureWitdh) * textureHeight;
                float heightScale = rectHeight / preferredRectHeight;
                float uvDeltaY = (1 - Mathf.Clamp01(heightScale)) * uvHeight;

                if (shapeAnchorsType == ShapeAnchors.Top || shapeAnchorsType == ShapeAnchors.TopLeft || shapeAnchorsType == ShapeAnchors.TopRight)
                {
                    uv.y += uvDeltaY;
                }
                else if (shapeAnchorsType == ShapeAnchors.Center || shapeAnchorsType == ShapeAnchors.Left || shapeAnchorsType == ShapeAnchors.Right)
                {
                    uv.y += uvDeltaY / 2;
                    uv.w -= uvDeltaY / 2;
                }
                else if (shapeAnchorsType == ShapeAnchors.Bottom || shapeAnchorsType == ShapeAnchors.BottomLeft || shapeAnchorsType == ShapeAnchors.BottomRight)
                {
                    uv.w -= uvDeltaY;
                }
            }

            return uv;
        }

        /// <summary>
        /// 绘制圆形图片
        /// </summary>
        void GenerateSimpleCircleSprite(VertexHelper vh, bool lPreserveAspect)
        {
            Sprite activeSprite = this.overrideSprite;
            Color32 color = this.color;
            vh.Clear();
            var uv = (activeSprite != null) ? Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero;
            uv = SetShapeAnchors(uv);
            uv = SetShapeScale(uv);
            uv = SetShapeAnchorsOffset(uv);
            if (m_ShapeAnchorsCalPadding)
            {
                uv = IncludePaddingUV(uv);
            }

            float tw = rectTransform.rect.width;
            float th = rectTransform.rect.height;
            float outerRadius = tw > th ? th / 2f : tw / 2f;
            float uvCenterX = (uv.x + uv.z) * 0.5f;
            float uvCenterY = (uv.y + uv.w) * 0.5f;
            float uvScaleX = (uv.z - uv.x) / tw;
            float uvScaleY = (uv.w - uv.y) / th;
            float degreeDelta = 2 * Mathf.PI / circleShape_Segements;
            int curSegements = (int)(circleShape_Segements * circleShape_FillPercent);

            Rect r = GetPixelAdjustedRect();
            float curDegree = 0;
            int verticeCount;
            int triangleCount;
            verticeCount = curSegements + 1;
            //圆心
            Vector3 centerVertice = new Vector3(r.x + r.width / 2f, r.y + r.height / 2f);
            vh.AddVert(centerVertice, color, new Vector2(uvCenterX, uvCenterY));
            Vector3 curVertice = new Vector3();
            for (int i = 1; i < verticeCount; i++)
            {
                float cosA = Mathf.Cos(curDegree);
                float sinA = Mathf.Sin(curDegree);
                float posX = cosA * outerRadius;
                float posY = sinA * outerRadius;
                curVertice.x = posX + centerVertice.x;
                curVertice.y = posY + centerVertice.y;
                vh.AddVert(curVertice, color, new Vector2(uvCenterX + posX * uvScaleX, uvCenterY + posY * uvScaleY));
                curDegree += degreeDelta;
            }
            triangleCount = curSegements * 3;
            for (int i = 0, vIdx = 1; i < triangleCount - 3; i += 3, vIdx++)
            {
                vh.AddTriangle(vIdx, 0, vIdx + 1);
            }
            if (circleShape_FillPercent == 1)
            {
                //首尾顶点相连
                vh.AddTriangle(verticeCount - 1, 0, 1);
            }
        }
        /// <summary>
        /// 绘制方形图片
        /// </summary>
        void GenerateSimpleSquareSprite(VertexHelper vh, bool lPreserveAspect)
        {
            Sprite activeSprite = this.overrideSprite;
            Color32 color = this.color;
            vh.Clear();
            var uv = (activeSprite != null) ? Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero;
            uv = SetShapeAnchors(uv);
            uv = SetShapeScale(uv);
            uv = SetShapeAnchorsOffset(uv);
            if (m_ShapeAnchorsCalPadding)
            {
                uv = IncludePaddingUV(uv);
            }
            //不计算padding
            Rect r = GetPixelAdjustedRect();
            float v_y = r.y;
            float v_w = r.y + r.height;
            float v_x = r.x;
            float v_z = r.x + r.width;

            vh.AddVert(new Vector3(v_x, v_y), color, new Vector2(uv.x, uv.y));
            vh.AddVert(new Vector3(v_x, v_w), color, new Vector2(uv.x, uv.w));
            vh.AddVert(new Vector3(v_z, v_w), color, new Vector2(uv.z, uv.w));
            vh.AddVert(new Vector3(v_z, v_y), color, new Vector2(uv.z, uv.y));

            vh.AddTriangle(0, 1, 2);
            vh.AddTriangle(2, 3, 0);
        }

        //绘制矩形图形
        void GenerateSimpleRectangleSprite(VertexHelper vh, bool lPreserveAspect)
        {
            Sprite activeSprite = this.overrideSprite;
            Color32 color = this.color;
            vh.Clear();
            var uv = (activeSprite != null) ? Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero;
            uv = SetRectangleShapeUV(uv);
            uv = SetShapeScale(uv);
            uv = SetShapeAnchorsOffset(uv);
            if (m_ShapeAnchorsCalPadding)
            {
                uv = IncludePaddingUV(uv);
            }

            Rect r = GetPixelAdjustedRect();

            float v_x = r.x;
            float v_y = r.y;
            float v_z = r.x + r.width;
            float v_w = r.y + r.height;

            vh.AddVert(new Vector3(v_x, v_y), color, new Vector2(uv.x, uv.y));
            vh.AddVert(new Vector3(v_x, v_w), color, new Vector2(uv.x, uv.w));
            vh.AddVert(new Vector3(v_z, v_w), color, new Vector2(uv.z, uv.w));
            vh.AddVert(new Vector3(v_z, v_y), color, new Vector2(uv.z, uv.y));

            vh.AddTriangle(0, 1, 2);
            vh.AddTriangle(2, 3, 0);
        }
        #endregion

        #region Various fill functions
        /// <summary>
        /// 生成Simple模式Sprite
        /// </summary>
        void GenerateSimpleSprite(VertexHelper vh, bool lPreserveAspect)
        {
            Sprite overrideSprite = this.overrideSprite;
            Color32 color = this.color;
            var uv = (overrideSprite != null) ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero;
            vh.Clear();

            Vector4 v = GetDrawingDimensions(lPreserveAspect);

            vh.AddVert(new Vector3(v.x, v.y), color, new Vector2(uv.x, uv.y));
            vh.AddVert(new Vector3(v.x, v.w), color, new Vector2(uv.x, uv.w));
            vh.AddVert(new Vector3(v.z, v.w), color, new Vector2(uv.z, uv.w));
            vh.AddVert(new Vector3(v.z, v.y), color, new Vector2(uv.z, uv.y));

            vh.AddTriangle(0, 1, 2);
            vh.AddTriangle(2, 3, 0);
        }
        protected static readonly Vector2[] s_VertScratch = new Vector2[4];
        protected static readonly Vector2[] s_UVScratch = new Vector2[4];

        /// <summary>
        /// 生成九宫格模式Sprite
        /// </summary>
        /// <param name="toFill"></param>
        private void GenerateSlicedSprite(VertexHelper toFill)
        {
            if (!hasBorder)
            {
                GenerateSimpleSprite(toFill, false);
                return;
            }

            Sprite overrideSprite = this.overrideSprite;
            Color32 color = this.color;

            Vector4 outer, inner, border;
            if (overrideSprite != null)
            {
                outer = DataUtility.GetOuterUV(overrideSprite);
                inner = DataUtility.GetInnerUV(overrideSprite);
                border = overrideSprite.border;
            }
            else
            {
                outer = Vector4.zero;
                inner = Vector4.zero;
                border = Vector4.zero;
            }
            Rect rect = GetPixelAdjustedRect();
            border = GetAdjustedBorders(border / pixelsPerUnit, rect);
            Vector4 v = GetSlicedDiamons();

            s_VertScratch[0] = new Vector2(v.x, v.y);
            s_VertScratch[3] = new Vector2(v.z, v.w);

            s_VertScratch[1].x = border.x + s_VertScratch[0].x;
            s_VertScratch[1].y = border.y + s_VertScratch[0].y;
            s_VertScratch[2].x = s_VertScratch[3].x - border.z;
            s_VertScratch[2].y = s_VertScratch[3].y - border.w;

            s_UVScratch[0] = new Vector2(outer.x, outer.y);
            s_UVScratch[1] = new Vector2(inner.x, inner.y);
            s_UVScratch[2] = new Vector2(inner.z, inner.w);
            s_UVScratch[3] = new Vector2(outer.z, outer.w);

            toFill.Clear();
            for (int x = 0; x < 3; ++x)
            {
                int x2 = x + 1;
                for (int y = 0; y < 3; ++y)
                {
                    if (!fillCenter && x == 1 && y == 1)
                        continue;
                    int y2 = y + 1;
                    AddQuad(toFill,
                        new Vector2(s_VertScratch[x].x, s_VertScratch[y].y),
                        new Vector2(s_VertScratch[x2].x, s_VertScratch[y2].y),
                        color,
                        new Vector2(s_UVScratch[x].x, s_UVScratch[y].y),
                        new Vector2(s_UVScratch[x2].x, s_UVScratch[y2].y));
                }
            }
        }

        /// <summary>
        /// 生成Tiled模式Sprite
        /// </summary>
        void GenerateTiledSprite(VertexHelper toFill)
        {
            Vector4 outer, inner, border;
            Vector2 spriteSize;

            Sprite overrideSprite = this.overrideSprite;
            Color32 color = this.color;

            if (overrideSprite != null)
            {
                outer = DataUtility.GetOuterUV(overrideSprite);
                inner = DataUtility.GetInnerUV(overrideSprite);
                border = overrideSprite.border;
                spriteSize = overrideSprite.rect.size;
            }
            else
            {
                outer = Vector4.zero;
                inner = Vector4.zero;
                border = Vector4.zero;
                spriteSize = Vector2.one * 100;
            }

            Rect rect = GetPixelAdjustedRect();
            float tileWidth = (spriteSize.x - border.x - border.z) / pixelsPerUnit;
            float tileHeight = (spriteSize.y - border.y - border.w) / pixelsPerUnit;
            border = GetAdjustedBorders(border / pixelsPerUnit, rect);

            var uvMin = new Vector2(inner.x, inner.y);
            var uvMax = new Vector2(inner.z, inner.w);

            var v = UIVertex.simpleVert;
            v.color = color;

            // Min to max max range for tiled region in coordinates relative to lower left corner.
            float xMin = border.x;
            float xMax = rect.width - border.z;
            float yMin = border.y;
            float yMax = rect.height - border.w;

            toFill.Clear();
            var clipped = uvMax;

            // if either with is zero we cant tile so just assume it was the full width.
            if (tileWidth <= 0)
                tileWidth = xMax - xMin;

            if (tileHeight <= 0)
                tileHeight = yMax - yMin;

            if (fillCenter)
            {
                for (float y1 = yMin; y1 < yMax; y1 += tileHeight)
                {
                    float y2 = y1 + tileHeight;
                    if (y2 > yMax)
                    {
                        clipped.y = uvMin.y + (uvMax.y - uvMin.y) * (yMax - y1) / (y2 - y1);
                        y2 = yMax;
                    }

                    clipped.x = uvMax.x;
                    for (float x1 = xMin; x1 < xMax; x1 += tileWidth)
                    {
                        float x2 = x1 + tileWidth;
                        if (x2 > xMax)
                        {
                            clipped.x = uvMin.x + (uvMax.x - uvMin.x) * (xMax - x1) / (x2 - x1);
                            x2 = xMax;
                        }
                        AddQuad(toFill, new Vector2(x1, y1) + rect.position, new Vector2(x2, y2) + rect.position, color, uvMin, clipped);
                    }
                }
            }

            if (hasBorder)
            {
                clipped = uvMax;
                for (float y1 = yMin; y1 < yMax; y1 += tileHeight)
                {
                    float y2 = y1 + tileHeight;
                    if (y2 > yMax)
                    {
                        clipped.y = uvMin.y + (uvMax.y - uvMin.y) * (yMax - y1) / (y2 - y1);
                        y2 = yMax;
                    }
                    AddQuad(toFill,
                        new Vector2(0, y1) + rect.position,
                        new Vector2(xMin, y2) + rect.position,
                        color,
                        new Vector2(outer.x, uvMin.y),
                        new Vector2(uvMin.x, clipped.y));
                    AddQuad(toFill,
                        new Vector2(xMax, y1) + rect.position,
                        new Vector2(rect.width, y2) + rect.position,
                        color,
                        new Vector2(uvMax.x, uvMin.y),
                        new Vector2(outer.z, clipped.y));
                }

                // Bottom and top tiled border
                clipped = uvMax;
                for (float x1 = xMin; x1 < xMax; x1 += tileWidth)
                {
                    float x2 = x1 + tileWidth;
                    if (x2 > xMax)
                    {
                        clipped.x = uvMin.x + (uvMax.x - uvMin.x) * (xMax - x1) / (x2 - x1);
                        x2 = xMax;
                    }
                    AddQuad(toFill,
                        new Vector2(x1, 0) + rect.position,
                        new Vector2(x2, yMin) + rect.position,
                        color,
                        new Vector2(uvMin.x, outer.y),
                        new Vector2(clipped.x, uvMin.y));
                    AddQuad(toFill,
                        new Vector2(x1, yMax) + rect.position,
                        new Vector2(x2, rect.height) + rect.position,
                        color,
                        new Vector2(uvMin.x, uvMax.y),
                        new Vector2(clipped.x, outer.w));
                }

                // Corners
                AddQuad(toFill,
                    new Vector2(0, 0) + rect.position,
                    new Vector2(xMin, yMin) + rect.position,
                    color,
                    new Vector2(outer.x, outer.y),
                    new Vector2(uvMin.x, uvMin.y));
                AddQuad(toFill,
                    new Vector2(xMax, 0) + rect.position,
                    new Vector2(rect.width, yMin) + rect.position,
                    color,
                    new Vector2(uvMax.x, outer.y),
                    new Vector2(outer.z, uvMin.y));
                AddQuad(toFill,
                    new Vector2(0, yMax) + rect.position,
                    new Vector2(xMin, rect.height) + rect.position,
                    color,
                    new Vector2(outer.x, uvMax.y),
                    new Vector2(uvMin.x, outer.w));
                AddQuad(toFill,
                    new Vector2(xMax, yMax) + rect.position,
                    new Vector2(rect.width, rect.height) + rect.position,
                    color,
                    new Vector2(uvMax.x, uvMax.y),
                    new Vector2(outer.z, outer.w));
            }
        }

        static void AddQuad(VertexHelper vertexHelper, Vector3[] quadPositions, Color32 color, Vector3[] quadUVs)
        {
            int startIndex = vertexHelper.currentVertCount;

            for (int i = 0; i < 4; ++i)
                vertexHelper.AddVert(quadPositions[i], color, quadUVs[i]);

            vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
            vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
        }

        static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, Color32 color, Vector2 uvMin, Vector2 uvMax)
        {
            int startIndex = vertexHelper.currentVertCount;

            vertexHelper.AddVert(new Vector3(posMin.x, posMin.y, 0), color, new Vector2(uvMin.x, uvMin.y));
            vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, 0), color, new Vector2(uvMin.x, uvMax.y));
            vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, 0), color, new Vector2(uvMax.x, uvMax.y));
            vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, 0), color, new Vector2(uvMax.x, uvMin.y));

            vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
            vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
        }

        protected Vector4 GetAdjustedBorders(Vector4 border, Rect rect)
        {
            for (int axis = 0; axis <= 1; axis++)
            {
                // If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
                // In order to avoid artefacts with overlapping borders, we scale the borders down to fit.
                float combinedBorders = border[axis] + border[axis + 2];
                if (rect.size[axis] < combinedBorders && combinedBorders != 0)
                {
                    float borderScaleRatio = rect.size[axis] / combinedBorders;
                    border[axis] *= borderScaleRatio;
                    border[axis + 2] *= borderScaleRatio;
                }
            }
            return border;
        }

        /// <summary>
        /// 生成Filled模式Sprite
        /// </summary>
        static readonly Vector3[] s_Xy = new Vector3[4];
        static readonly Vector3[] s_Uv = new Vector3[4];
        void GenerateFilledSprite(VertexHelper toFill, bool preserveAspect)
        {
            toFill.Clear();

            if (fillAmount < 0.001f)
                return;

            Sprite overrideSprite = this.overrideSprite;
            Color32 color = this.color;

            Vector4 v = GetDrawingDimensions(preserveAspect);
            Vector4 outer = overrideSprite != null ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero;
            UIVertex uiv = UIVertex.simpleVert;
            uiv.color = color;

            float tx0 = outer.x;
            float ty0 = outer.y;
            float tx1 = outer.z;
            float ty1 = outer.w;

            // Horizontal and vertical filled sprites are simple -- just end the Image prematurely
            if (fillMethod == FillMethod.Horizontal || fillMethod == FillMethod.Vertical)
            {
                if (fillMethod == FillMethod.Horizontal)
                {
                    float fill = (tx1 - tx0) * fillAmount;

                    if (fillOrigin == 1)
                    {
                        v.x = v.z - (v.z - v.x) * fillAmount;
                        tx0 = tx1 - fill;
                    }
                    else
                    {
                        v.z = v.x + (v.z - v.x) * fillAmount;
                        tx1 = tx0 + fill;
                    }
                }
                else if (fillMethod == FillMethod.Vertical)
                {
                    float fill = (ty1 - ty0) * fillAmount;

                    if (fillOrigin == 1)
                    {
                        v.y = v.w - (v.w - v.y) * fillAmount;
                        ty0 = ty1 - fill;
                    }
                    else
                    {
                        v.w = v.y + (v.w - v.y) * fillAmount;
                        ty1 = ty0 + fill;
                    }
                }
            }

            s_Xy[0] = new Vector2(v.x, v.y);
            s_Xy[1] = new Vector2(v.x, v.w);
            s_Xy[2] = new Vector2(v.z, v.w);
            s_Xy[3] = new Vector2(v.z, v.y);

            s_Uv[0] = new Vector2(tx0, ty0);
            s_Uv[1] = new Vector2(tx0, ty1);
            s_Uv[2] = new Vector2(tx1, ty1);
            s_Uv[3] = new Vector2(tx1, ty0);

            {
                if (fillAmount < 1f && fillMethod != FillMethod.Horizontal && fillMethod != FillMethod.Vertical)
                {
                    if (fillMethod == FillMethod.Radial90)
                    {
                        if (RadialCut(s_Xy, s_Uv, fillAmount, fillClockwise, fillOrigin))
                            AddQuad(toFill, s_Xy, color, s_Uv);
                    }
                    else if (fillMethod == FillMethod.Radial180)
                    {
                        for (int side = 0; side < 2; ++side)
                        {
                            float fx0, fx1, fy0, fy1;
                            int even = fillOrigin > 1 ? 1 : 0;

                            if (fillOrigin == 0 || fillOrigin == 2)
                            {
                                fy0 = 0f;
                                fy1 = 1f;
                                if (side == even)
                                {
                                    fx0 = 0f;
                                    fx1 = 0.5f;
                                }
                                else
                                {
                                    fx0 = 0.5f;
                                    fx1 = 1f;
                                }
                            }
                            else
                            {
                                fx0 = 0f;
                                fx1 = 1f;
                                if (side == even)
                                {
                                    fy0 = 0.5f;
                                    fy1 = 1f;
                                }
                                else
                                {
                                    fy0 = 0f;
                                    fy1 = 0.5f;
                                }
                            }

                            s_Xy[0].x = Mathf.Lerp(v.x, v.z, fx0);
                            s_Xy[1].x = s_Xy[0].x;
                            s_Xy[2].x = Mathf.Lerp(v.x, v.z, fx1);
                            s_Xy[3].x = s_Xy[2].x;

                            s_Xy[0].y = Mathf.Lerp(v.y, v.w, fy0);
                            s_Xy[1].y = Mathf.Lerp(v.y, v.w, fy1);
                            s_Xy[2].y = s_Xy[1].y;
                            s_Xy[3].y = s_Xy[0].y;

                            s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0);
                            s_Uv[1].x = s_Uv[0].x;
                            s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1);
                            s_Uv[3].x = s_Uv[2].x;

                            s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0);
                            s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1);
                            s_Uv[2].y = s_Uv[1].y;
                            s_Uv[3].y = s_Uv[0].y;

                            float val = fillClockwise ? fillAmount * 2f - side : fillAmount * 2f - (1 - side);

                            if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), fillClockwise, ((side + fillOrigin + 3) % 4)))
                            {
                                AddQuad(toFill, s_Xy, color, s_Uv);
                            }
                        }
                    }
                    else if (fillMethod == FillMethod.Radial360)
                    {
                        for (int corner = 0; corner < 4; ++corner)
                        {
                            float fx0, fx1, fy0, fy1;

                            if (corner < 2)
                            {
                                fx0 = 0f;
                                fx1 = 0.5f;
                            }
                            else
                            {
                                fx0 = 0.5f;
                                fx1 = 1f;
                            }

                            if (corner == 0 || corner == 3)
                            {
                                fy0 = 0f;
                                fy1 = 0.5f;
                            }
                            else
                            {
                                fy0 = 0.5f;
                                fy1 = 1f;
                            }

                            s_Xy[0].x = Mathf.Lerp(v.x, v.z, fx0);
                            s_Xy[1].x = s_Xy[0].x;
                            s_Xy[2].x = Mathf.Lerp(v.x, v.z, fx1);
                            s_Xy[3].x = s_Xy[2].x;

                            s_Xy[0].y = Mathf.Lerp(v.y, v.w, fy0);
                            s_Xy[1].y = Mathf.Lerp(v.y, v.w, fy1);
                            s_Xy[2].y = s_Xy[1].y;
                            s_Xy[3].y = s_Xy[0].y;

                            s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0);
                            s_Uv[1].x = s_Uv[0].x;
                            s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1);
                            s_Uv[3].x = s_Uv[2].x;

                            s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0);
                            s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1);
                            s_Uv[2].y = s_Uv[1].y;
                            s_Uv[3].y = s_Uv[0].y;

                            float val = fillClockwise ?
                                fillAmount * 4f - ((corner + fillOrigin) % 4) :
                                fillAmount * 4f - (3 - ((corner + fillOrigin) % 4));

                            if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), fillClockwise, ((corner + 2) % 4)))
                                AddQuad(toFill, s_Xy, color, s_Uv);
                        }
                    }
                }
                else
                {
                    AddQuad(toFill, s_Xy, color, s_Uv);
                }
            }
        }

        /// <summary>
        /// Adjust the specified quad, making it be radially filled instead.
        /// </summary>
        static bool RadialCut(Vector3[] xy, Vector3[] uv, float fill, bool invert, int corner)
        {
            // Nothing to fill
            if (fill < 0.001f) return false;

            // Even corners invert the fill direction
            if ((corner & 1) == 1) invert = !invert;

            // Nothing to adjust
            if (!invert && fill > 0.999f) return true;

            // Convert 0-1 value into 0 to 90 degrees angle in radians
            float angle = Mathf.Clamp01(fill);
            if (invert) angle = 1f - angle;
            angle *= 90f * Mathf.Deg2Rad;

            // Calculate the effective X and Y factors
            float cos = Mathf.Cos(angle);
            float sin = Mathf.Sin(angle);

            RadialCut(xy, cos, sin, invert, corner);
            RadialCut(uv, cos, sin, invert, corner);
            return true;
        }

        /// <summary>
        /// Adjust the specified quad, making it be radially filled instead.
        /// </summary>
        static void RadialCut(Vector3[] xy, float cos, float sin, bool invert, int corner)
        {
            int i0 = corner;
            int i1 = ((corner + 1) % 4);
            int i2 = ((corner + 2) % 4);
            int i3 = ((corner + 3) % 4);

            if ((corner & 1) == 1)
            {
                if (sin > cos)
                {
                    cos /= sin;
                    sin = 1f;

                    if (invert)
                    {
                        xy[i1].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
                        xy[i2].x = xy[i1].x;
                    }
                }
                else if (cos > sin)
                {
                    sin /= cos;
                    cos = 1f;

                    if (!invert)
                    {
                        xy[i2].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
                        xy[i3].y = xy[i2].y;
                    }
                }
                else
                {
                    cos = 1f;
                    sin = 1f;
                }

                if (!invert) xy[i3].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
                else xy[i1].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
            }
            else
            {
                if (cos > sin)
                {
                    sin /= cos;
                    cos = 1f;

                    if (!invert)
                    {
                        xy[i1].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
                        xy[i2].y = xy[i1].y;
                    }
                }
                else if (sin > cos)
                {
                    cos /= sin;
                    sin = 1f;

                    if (invert)
                    {
                        xy[i2].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
                        xy[i3].x = xy[i2].x;
                    }
                }
                else
                {
                    cos = 1f;
                    sin = 1f;
                }

                if (invert) xy[i3].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin);
                else xy[i1].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos);
            }
        }
        #endregion

        public void SetImage(string url)
        {
            TaskManager.CreateTask(LoadImage(url)).Start();
        }

        IEnumerator LoadImage(string url)
        {
            WWW www = new WWW(url);
            yield return www;
            if (string.IsNullOrEmpty(www.error))
            {
                Texture2D tex = www.texture;
                Sprite temp = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0, 0));
                sprite = temp;
                m_Material = null;
            }
        }

        /// <summary>
        /// 重写这个MaskableGraphic的虚函数，默认实现的getcomponent很耗
        /// </summary>
        /// <param name="baseMaterial"></param>
        /// <returns></returns>
        public override Material GetModifiedMaterial(Material baseMaterial)
        {
            var toUse = baseMaterial;

            if (m_ShouldRecalculateStencil)
            {
                var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
                m_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0;
                m_ShouldRecalculateStencil = false;
            }

            // if we have a Mask component then it will
            // generate the mask material. This is an optimisation
            // it adds some coupling between components though :(
            if (m_StencilValue > 0 && CachedMask == null)
            {
                var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, Rendering.StencilOp.Keep, Rendering.CompareFunction.Equal, Rendering.ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);
                StencilMaterial.Remove(m_MaskMaterial);
                m_MaskMaterial = maskMat;
                toUse = m_MaskMaterial;
            }
            return toUse;
        }

        public void SetPreferredWidth(float preferredWidth)
        {
            if (sprite && sprite.rect != null)
            {
                float preferredHeight = preferredWidth / (sprite.rect.width / sprite.rect.height);
                rectTransform.sizeDelta = new Vector2(preferredWidth, preferredHeight);
            }
        }

        public void SetPreferredHeight(float preferredHeight)
        {
            if (sprite && sprite.rect != null)
            {
                float preferredWidth = preferredHeight * (sprite.rect.width / sprite.rect.height);
                rectTransform.sizeDelta = new Vector2(preferredWidth, preferredHeight);
            }
        }
        #region Cull显隐方式
        bool _cullNeedRebuild = false;
        bool _hasInitPopulateMesh = false;
        public bool m_Cull
        {
            get
            {
                return canvasRenderer.cull;
            }
            set
            {
                canvasRenderer.cull = value;
                if ((_cullNeedRebuild && !value) || (!_hasInitPopulateMesh && !value))
                {
                    SetVerticesDirty();
                    _cullNeedRebuild = false;
                }
            }
        }
        // protected override void OnEnable()
        // {
        //     base.OnEnable();
        //     if(m_Cull){
        //         _cullNeedRebuild = true;
        //     }
        // }
        // protected override void OnDisable()
        // {
        //     base.OnDisable();
        //     _cullNeedRebuild = false;
        // }
        public override void Rebuild(CanvasUpdate update)
        {
            base.Rebuild(update);
            if (m_Cull)
            {
                _cullNeedRebuild = true;
            }
        }
        #endregion
        public override void SetNativeSize()
        {
            var overrideSprite = this.overrideSprite;
            if (overrideSprite != null)
            {
                float w;
                float h;
                if (!m_UseSpritePacker)
                {
                    var padding = GetPadding();
                    w = (overrideSprite.rect.width + padding.x + padding.z) / pixelsPerUnit;
                    h = (overrideSprite.rect.height + padding.y + padding.w) / pixelsPerUnit;
                }
                else
                {
                    w = overrideSprite.rect.width / pixelsPerUnit;
                    h = overrideSprite.rect.height / pixelsPerUnit;
                }
                rectTransform.anchorMax = rectTransform.anchorMin;
                rectTransform.sizeDelta = new Vector2(w, h);
                SetAllDirty();
            }
        }
    }
}
